package cn.stylefeng.guns.modular.business.frequency.cmprovince.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.stylefeng.guns.core.exception.ServiceException;
import cn.stylefeng.guns.core.factory.PageFactory;
import cn.stylefeng.guns.core.pojo.base.node.BaseTreeNode;
import cn.stylefeng.guns.core.pojo.node.CommonBaseTreeNode;
import cn.stylefeng.guns.core.pojo.page.AndaPageResult;
import cn.stylefeng.guns.core.pojo.page.PageResult;
import cn.stylefeng.guns.core.pojo.response.ResponseData;
import cn.stylefeng.guns.modular.business.custom.enums.RedisKey;
import cn.stylefeng.guns.modular.business.frequency.cmarea.entity.CmArea;
import cn.stylefeng.guns.modular.business.frequency.cmarea.mapper.CmAreaMapper;
import cn.stylefeng.guns.modular.business.frequency.cmcity.entity.CmCity;
import cn.stylefeng.guns.modular.business.frequency.cmcity.mapper.CmCityMapper;
import cn.stylefeng.guns.modular.business.frequency.cmcity.model.result.TreeNodeCity;
import cn.stylefeng.guns.modular.business.frequency.cmprovince.entity.CmProvince;
import cn.stylefeng.guns.modular.business.frequency.cmprovince.enums.CmProvinceExceptionEnum;
import cn.stylefeng.guns.modular.business.frequency.cmprovince.mapper.CmProvinceMapper;
import cn.stylefeng.guns.modular.business.frequency.cmprovince.model.param.AdministrativeDivisionDTO;
import cn.stylefeng.guns.modular.business.frequency.cmprovince.model.param.CmProvinceParam;
import cn.stylefeng.guns.modular.business.frequency.cmprovince.model.result.PkgCmCity;
import cn.stylefeng.guns.modular.business.frequency.cmprovince.model.result.PkgProvince;
import cn.stylefeng.guns.modular.business.frequency.cmprovince.service.CmProvinceService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * cm_province 服务实现类
 *
 * @author yujie
 * @date 2023/05/09 17:17
 */
@Service
public class CmProvinceServiceImpl extends ServiceImpl<CmProvinceMapper, CmProvince> implements CmProvinceService {

    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private CmCityMapper cmCityMapper;

    @Autowired
    private CmAreaMapper cmAreaMapper;


    @Override
    public PageResult<CmProvince> page(CmProvinceParam cmProvinceParam) {

        // 构造条件
        LambdaQueryWrapper<CmProvince> queryWrapper = new LambdaQueryWrapper<>();

        // 查询分页结果
        return new PageResult<>(this.page(PageFactory.defaultPage(), queryWrapper));
    }

    @Override
    public List<CmProvince> list(CmProvinceParam cmProvinceParam) {

        // 构造条件
        LambdaQueryWrapper<CmProvince> queryWrapper = new LambdaQueryWrapper<>();

        return this.list(queryWrapper);
    }

    @Override
    public void add(CmProvinceParam cmProvinceParam) {

        // 校验参数，检查是否存在重复的编码或者名称，不排除当前添加的这条记录
        checkParam(cmProvinceParam, false);

        // 将dto转为实体
        CmProvince cmProvince = new CmProvince();
        BeanUtil.copyProperties(cmProvinceParam, cmProvince);

        this.save(cmProvince);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delete(CmProvinceParam cmProvinceParam) {
        this.removeById(cmProvinceParam.getCode());
    }

    @Override
    public void edit(CmProvinceParam cmProvinceParam) {

        // 根据id查询实体
        CmProvince cmProvince = this.queryCmProvince(cmProvinceParam);

        // 校验参数，检查是否存在重复的编码或者名称，排除当前编辑的这条记录
        checkParam(cmProvinceParam, true);

        // 请求参数转化为实体
        BeanUtil.copyProperties(cmProvinceParam, cmProvince);

        this.updateById(cmProvince);
    }

    @Override
    public CmProvince detail(CmProvinceParam cmProvinceParam) {
        return this.queryCmProvince(cmProvinceParam);
    }

    @Override
    public ResponseData getCityListPage(AdministrativeDivisionDTO administrativeDivisionDTO) {
        if (!StringUtils.isNotBlank(administrativeDivisionDTO.getColumn()) ) {
            // 默认排序
            administrativeDivisionDTO.setColumn("hasCounty");
        }
        Page<PkgCmCity> page = this.baseMapper.page(PageFactory.defaultPage(),administrativeDivisionDTO);
        return ResponseData.success(new AndaPageResult().AndaPageResult(page, administrativeDivisionDTO));
    }

    @Override
    public ResponseData getAllCityList() {
        AdministrativeDivisionDTO administrativeDivisionDTO = new AdministrativeDivisionDTO();
        List<PkgCmCity> list;
        if(redisTemplate.hasKey(RedisKey.CACHE_CITY_LIST)){
            Object object = redisTemplate.opsForValue().get(RedisKey.CACHE_CITY_LIST);
            if (object != null) {
                list = (List<PkgCmCity>) object;
            } else {
                list = cmCityMapper.getAllCityList(administrativeDivisionDTO);
                redisTemplate.opsForValue().set(RedisKey.CACHE_CITY_LIST, list);
            }
        }else {
            list = cmCityMapper.getAllCityList(administrativeDivisionDTO);
            redisTemplate.opsForValue().set(RedisKey.CACHE_CITY_LIST, list);
        }

        return ResponseData.success(list);
    }

    @Override
    public ResponseData getTreeAllCityList() {
        Object object = redisTemplate.opsForValue().get(RedisKey.CACHE_CITY_TREE_LIST);
        List<TreeNodeCity> list;
        if (ObjectUtil.isNotEmpty(object)) {
            list = (List<TreeNodeCity>) object;
        } else {
            list = cmCityMapper.getTreeProvinceCity();
            redisTemplate.opsForValue().set(RedisKey.CACHE_CITY_TREE_LIST, list);
        }
        return ResponseData.success(list);
    }

    @Override
    public ResponseData getAreaListByCityCode(String cityCode) {
        List<CmArea> list =  cmCityMapper.getAreaListByCityCode(cityCode);
        return ResponseData.success(list);
    }

    @Override
    public ResponseData getNonCountyCityByProvinceCode(String provinceCode) {
        List<CmCity> list = cmCityMapper.getNonCountyCityByProvinceCode(provinceCode);
        return ResponseData.success(list);
    }

    @Override
    public boolean checkCityAdd(CmCity city, ResponseData responseData) {
        // 城市code检查
        if (city.getCode().length() != 6) {
            responseData.setMessage("请输入6位数字的城市CODE码！");
            return false;
        }
        String provinceCodeSuffix = city.getProvinceCode().substring(0,1);
        if (!city.getCode().startsWith(provinceCodeSuffix)) {
            responseData.setMessage("城市CODE码错误，请输入【"+city.getProvinceName()+"】开头的CODE("+provinceCodeSuffix+")");
            return false;
        }
        int count = cmCityMapper.countByCode(false, city.getCode());
        if (count > 0) {
            responseData.setMessage("城市CODE码已存在！");
            return false;
        }
        // 如果是县级市需要所属地级市code
        if (city.getHasCounty() == 1 && StringUtils.isBlank(city.getCityCode())) {
            responseData.setMessage("县级市需要选择所属城市");
            return false;
        }
        // 赋值
        city.setProvinceName(cmCityMapper.getProvinceNameByProvinceCode(city.getProvinceCode()));
        if (StringUtils.isNotBlank(city.getCityCode())) {
            city.setCityName(cmCityMapper.getNameByCode(city.getCityCode()));
        }
        return true;
    }

    @Override
    public void addCity(CmCity city) {
        cmCityMapper.insert(city);
        deleteCityCache();
    }

    @Override
    public void deleteCity(String code) {
        cmCityMapper.deleteCity(code);
        deleteCityCache();
    }

    @Override
    public CmCity getCityByCode(String code) {
        return cmCityMapper.getCityByCode(code);
    }

    @Override
    public void updateCity(CmCity city) {
        cmCityMapper.update(city, new QueryWrapper<CmCity>().lambda().eq(CmCity::getCode, city.getCode())
                .and(wrapper -> wrapper.eq(CmCity::getHasDelete, 0)));
        deleteCityCache();
    }

    @Override
    public void addArea(CmArea area) {
        cmAreaMapper.insert(area);
    }

    @Override
    public void updateArea(CmArea area) {
        cmAreaMapper.updateById(area);
    }

    @Override
    public CmArea getAreaByCode(String code) {
        return cmAreaMapper.getAreaByCode(code);
    }

    @Override
    public List getAllAreaList() {
        return cmAreaMapper.selectList(new QueryWrapper<CmArea>().lambda().eq(CmArea::getHasDelete, 0));
    }

    @Override
    public List<CmProvince> getProvinceList() {
        return cmCityMapper.getProvinceList();
    }

    @Override
    public List<PkgProvince> getPkgProvinceCity() {
        return cmCityMapper.getPkgProvinceCity();
    }

    @Override
    public boolean checkAreaAdd(CmArea area, String message) {
        // 区code检查
        if (area.getCode().length() != 6) {
            message="请输入6位数字的区CODE码！";
            return false;
        }
        int count = cmAreaMapper.countByCode(false, area.getCode());
        if (count > 0) {
            message = "区CODE码已存在";
            return false;
        }
        if (!area.getCode().startsWith(area.getCityCode().substring(0,3)) || area.getCode().endsWith("00")) {
            message = "区CODE码错误！";
            return false;
        }
        // 县级市不能添加区
        CmCity city = cmCityMapper.getCityByCode(area.getCityCode());
        if (city != null && city.getHasCounty() == 1) {
            message = "县/县级市不可添加行政区";
            return false;
        }
        return true;
    }

    @Override
    public boolean checkAreaUpdate(CmArea area, String errorMsg) {
        return true;
    }

    @Override
    public void deleteArea(String code) {
        cmAreaMapper.deleteArea(code);
    }


    private void deleteCityCache() {
        if (redisTemplate.hasKey(RedisKey.CACHE_CITY_LIST)) {
            redisTemplate.delete(RedisKey.CACHE_CITY_LIST);
        }
        if (redisTemplate.hasKey(RedisKey.CACHE_CITY_TREE_LIST)) {
            redisTemplate.delete(RedisKey.CACHE_CITY_TREE_LIST);
        }
    }


    /**
     * 校验参数，检查是否存在重复的编码等
     *
     * @author yujie
     * @since 2023/05/09 17:17
     */
    private void checkParam(CmProvinceParam cmProvinceParam, boolean isExcludeSelf) {
        Integer id = cmProvinceParam.getCode();
        Integer code = cmProvinceParam.getCode();

        // 构建带code的查询条件
        LambdaQueryWrapper<CmProvince> queryWrapperByCode = new LambdaQueryWrapper<>();
        queryWrapperByCode.eq(CmProvince::getCode, code);

        // 如果排除自己，则增加查询条件主键id不等于本条id
        if (isExcludeSelf) {
            queryWrapperByCode.ne(CmProvince::getCode, id);
        }

        // 查询重复记录的数量
        int countByCode = this.count(queryWrapperByCode);

        // 如果存在重复的记录，抛出异常，直接返回前端
        if (countByCode >= 1) {
            throw new ServiceException(CmProvinceExceptionEnum.CODE_REPEAT);
        }
    }

    /**
     * 获取cm_province
     *
     * @author yujie
     * @since 2023/05/09 17:17
     */
    private CmProvince queryCmProvince(CmProvinceParam cmProvinceParam) {
        CmProvince cmProvince = this.getById(cmProvinceParam.getCode());
        if (ObjectUtil.isEmpty(cmProvince)) {
            throw new ServiceException(CmProvinceExceptionEnum.NOT_EXISTED);
        }
        return cmProvince;
    }
}